/*jslint browser: true*/

/*jslint jquery: true*/



/*

 * jQuery Hotkeys Plugin

 * Copyright 2010, John Resig

 * Dual licensed under the MIT or GPL Version 2 licenses.

 *

 * Based upon the plugin by Tzury Bar Yochay:

 * https://github.com/tzuryby/jquery.hotkeys

 *

 * Original idea by:

 * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/

 */



/*

 * One small change is: now keys are passed by object { keys: '...' }

 * Might be useful, when you want to pass some other data to your handler

 */



(function(jQuery) {



    jQuery.hotkeys = {

        version: "0.2.0",



        specialKeys: {

            8: "backspace",

            9: "tab",

            10: "return",

            13: "return",

            16: "shift",

            17: "ctrl",

            18: "alt",

            19: "pause",

            20: "capslock",

            27: "esc",

            32: "space",

            33: "pageup",

            34: "pagedown",

            35: "end",

            36: "home",

            37: "left",

            38: "up",

            39: "right",

            40: "down",

            45: "insert",

            46: "del",

            59: ";",

            61: "=",

            96: "0",

            97: "1",

            98: "2",

            99: "3",

            100: "4",

            101: "5",

            102: "6",

            103: "7",

            104: "8",

            105: "9",

            106: "*",

            107: "+",

            109: "-",

            110: ".",

            111: "/",

            112: "f1",

            113: "f2",

            114: "f3",

            115: "f4",

            116: "f5",

            117: "f6",

            118: "f7",

            119: "f8",

            120: "f9",

            121: "f10",

            122: "f11",

            123: "f12",

            144: "numlock",

            145: "scroll",

            173: "-",

            186: ";",

            187: "=",

            188: ",",

            189: "-",

            190: ".",

            191: "/",

            192: "`",

            219: "[",

            220: "\\",

            221: "]",

            222: "'"

        },



        shiftNums: {

            "`": "~",

            "1": "!",

            "2": "@",

            "3": "#",

            "4": "$",

            "5": "%",

            "6": "^",

            "7": "&",

            "8": "*",

            "9": "(",

            "0": ")",

            "-": "_",

            "=": "+",

            ";": ": ",

            "'": "\"",

            ",": "<",

            ".": ">",

            "/": "?",

            "\\": "|"

        },



        // excludes: button, checkbox, file, hidden, image, password, radio, reset, search, submit, url

        textAcceptingInputTypes: [

            "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime",

            "datetime-local", "search", "color", "tel"],



        // default input types not to bind to unless bound directly

        textInputTypes: /textarea|input|select/i,



        options: {

            filterInputAcceptingElements: true,

            filterTextInputs: true,

            filterContentEditable: true

        }

    };



    function keyHandler(handleObj) {

        if (typeof handleObj.data === "string") {

            handleObj.data = {

                keys: handleObj.data

            };

        }



        // Only care when a possible input has been specified

        if (!handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string") {

            return;

        }



        var origHandler = handleObj.handler,

            keys = handleObj.data.keys.toLowerCase().split(" ");



        handleObj.handler = function(event) {

            //      Don't fire in text-accepting inputs that we didn't directly bind to

            if (this !== event.target &&

                (jQuery.hotkeys.options.filterInputAcceptingElements &&

                    jQuery.hotkeys.textInputTypes.test(event.target.nodeName) ||

                    (jQuery.hotkeys.options.filterContentEditable && jQuery(event.target).attr('contenteditable')) ||

                    (jQuery.hotkeys.options.filterTextInputs &&

                        jQuery.inArray(event.target.type, jQuery.hotkeys.textAcceptingInputTypes) > -1))) {

                return;

            }



            var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which],

                character = String.fromCharCode(event.which).toLowerCase(),

                modif = "",

                possible = {};



            jQuery.each(["alt", "ctrl", "shift"], function(index, specialKey) {



                if (event[specialKey + 'Key'] && special !== specialKey) {

                    modif += specialKey + '+';

                }

            });



            // metaKey is triggered off ctrlKey erronously

            if (event.metaKey && !event.ctrlKey && special !== "meta") {

                modif += "meta+";

            }



            if (event.metaKey && special !== "meta" && modif.indexOf("alt+ctrl+shift+") > -1) {

                modif = modif.replace("alt+ctrl+shift+", "hyper+");

            }



            if (special) {

                possible[modif + special] = true;

            }

            else {

                possible[modif + character] = true;

                possible[modif + jQuery.hotkeys.shiftNums[character]] = true;



                // "$" can be triggered as "Shift+4" or "Shift+$" or just "$"

                if (modif === "shift+") {

                    possible[jQuery.hotkeys.shiftNums[character]] = true;

                }

            }



            for (var i = 0, l = keys.length; i < l; i++) {

                if (possible[keys[i]]) {

                    return origHandler.apply(this, arguments);

                }

            }

        };

    }



    jQuery.each(["keydown", "keyup", "keypress"], function() {

        jQuery.event.special[this] = {

            add: keyHandler

        };

    });



})(jQuery || this.jQuery || window.jQuery);